package lionel.MyJMRI.MyTrain;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

import net.iharder.dnd.FileDrop;

import jmri.jmrit.XmlFile;
import jmri.jmrit.roster.Roster;
import jmri.jmrit.roster.RosterEntry;
import jmri.util.JmriJFrame;
import jmri.DccLocoAddress;
import jmri.LocoAddress;

import lionel.MyBrowser.MyBrowsableElement;
import lionel.MyBrowser.MyConductor;

public class MyLocomotive extends JDesktopPane implements MyBrowsableElement, Comparable<MyLocomotive>, FileDrop.Listener
{
	private static final long serialVersionUID = -6433251119286601527L;

	static org.apache.log4j.Category log = org.apache.log4j.Category.getInstance(MyLocomotive.class.getName());

	static final String PATH_BASE = XmlFile.prefsDir()+"MyJMRI/";
	static final String PATH_FILE = "/image";
	static final String PATH_EXT =".jpg";

	protected String mID = null;

	protected RosterEntry mRoster = null;
	protected JLabel bgImg = null;
	protected JmriJFrame mContainer = null;

	protected MyLocomotive(String id)  // fake constructor only for comparison
	{
		super();
		if (id == null)
		{
			log.error("MyLocomotive() with null String");
			return;
		}
		this.mID = id;
	}

	protected MyLocomotive(MyLocomotive myLoc) 
	{ 
		super();
		if (myLoc == null)
		{
			log.error("MyLocomotive() with null MyLocomotive");
			return;
		}		
		this.mID = myLoc.ID();
		this.mRoster = myLoc.getRoster();
		loadImage();
		this.setDoubleBuffered(true);
		new FileDrop(this, this);
	}

	protected RosterEntry getRoster() {
		return mRoster;
	}

	public int compareTo(MyLocomotive otherLoc) {
		return ( mID.compareTo(otherLoc.ID()));
	}

	public MyLocomotive(RosterEntry roster) {
		super();
		if (roster == null)
		{
			log.error("MyLocomotive() with null RosterEntry");
			return;
		}
		this.setDoubleBuffered(true);
		mID = roster.getModel() + " - " + roster.getRoadName() + " " + roster.getRoadNumber();
		mRoster  = roster;
		loadImage();
		new FileDrop(this, this);
	}

	public MyLocomotive(LocoAddress address) {
		super();
		if (address == null)
		{
			log.error("MyLocomotive() with null LocoAddress");
			return;
		}
		List<RosterEntry> rosters;
		rosters = (List<RosterEntry>) Roster.instance().matchingList(null, null, ""+((DccLocoAddress)address).getNumber(), null, null, null, null) ;
		if (rosters.size() == 0)
		{
			log.warn("No roster for "+address);
			return ;
		}			
		if (rosters.size() != 1)
		{
			log.warn("Several rosters for "+address+", using first one");
		}
		RosterEntry roster = rosters.get(0);
		mID = roster.getModel() + " - " + roster.getRoadName() + " " + roster.getRoadNumber();
		this.setDoubleBuffered(true);
		loadImage();
		new FileDrop(this, this);
	}

	private Boolean mDisplayed = false;

	public boolean isDisplayed()
	{ synchronized (mDisplayed) { return mDisplayed; } }

	public void setDisplayed(boolean dis)
	{ synchronized (mDisplayed) { mDisplayed = dis; }	}

	public void filesDropped(File[] files) {
		if (files == null)
			return;
		if (files.length == 0)
			return;
		setImage(files[0]);		
	}

	protected void loadImage()
	{
		String imagePath = PATH_BASE + mID.trim() + PATH_FILE;

		int i=0;
		File file = new File(imagePath +i + PATH_EXT);
		while ( file.exists() )
		{ i++ ; file = new File(imagePath + i + PATH_EXT); }
		if (i>0)
			i--;
		log.debug("Loading image for "+mID + ", "+i+"th file");
		loadImage( imagePath + i + PATH_EXT  );
	}
	
	public void loadImage(String path)
	{ SwingUtilities.invokeLater(new loadImage( path  )); }

	class loadImage implements Runnable {
		String path;
		public loadImage(String pPath)
		{ path = pPath; }

		public void run() {
			ImageIcon image =  new ImageIcon( path );		
			if ((image==null) || (image.getIconWidth() == -1)) 
			{	
				try {
					if (mRoster == null)
						image =  new ImageIcon(getClass().getResource("NoLocImage.jpg") );
					else if (mRoster.getDccAddress() == "0")
						image =  new ImageIcon(getClass().getResource("DCImage.jpg") );
					else if (mRoster.getDccAddress() == "3")
						image =  new ImageIcon(getClass().getResource("DCCImage.jpg") );
					else
						image =  new ImageIcon(getClass().getResource("NoLocImage.jpg") );
				} catch (Exception e) {
					log.error("Error while loading image for "+mID);
					e.printStackTrace();
				}
			}
			if (bgImg == null)
			{
				bgImg = new JLabel(image);
				add(bgImg, new Integer(Integer.MIN_VALUE));
			}
			else
				bgImg.setIcon(image);
			bgImg.setBounds(0, 0,image.getIconWidth(), image.getIconHeight());
			setPreferredSize( bgImg.getPreferredSize() );
			if (mContainer != null)
			{			
				mContainer.setPreferredSize(getPreferredSize());
				mContainer.pack();			
			}
		}
	}

	public void setImage(File file)  
	{
		if (mID == null)
		{ log.warn("No roster at the moment"); return; }

		String imagePath;
		synchronized(mID) {	// need synchro because it's ran by the dnd listener thread
			imagePath = PATH_BASE + mID.trim() + PATH_FILE ; 
		}
		int i=0;
		File copy = new File(imagePath +i + PATH_EXT);
		while ( copy.exists() ) 
		{ i++ ; copy = new File(imagePath +i + PATH_EXT); }

		if (i==0)
			copy.getParentFile().mkdirs();			

		if ( copy.getParentFile().compareTo( file.getParentFile() ) != 0 )
		{  // copy file
			try
			{ copyFile(file, copy); }
			catch (Exception e) 
			{ log.warn("Exception while copying file: "+e.toString()); }
		}
		else // move file in list
		{
			File prev = file;
			file.renameTo(copy); // rename to that name that will be loaded
			try
			{ prev.createNewFile(); } //create an empty file to fill slot
			catch (Exception e) 
			{ log.warn("Exception while creating empty file: "+e.toString()); }
		}

		log.debug("File copied to "+ imagePath +i + PATH_EXT);
		loadImage();
	}

	private static void copyFile(File in, File out) throws Exception {
		FileInputStream fis  = new FileInputStream(in);
		FileOutputStream fos = new FileOutputStream(out);
		try {
			byte[] buf = new byte[1024];
			int i = 0;
			while ((i = fis.read(buf)) != -1) {
				fos.write(buf, 0, i);
			}
		} 
		catch (Exception e) {
			throw e;
		}
		finally {
			if (fis != null) fis.close();
			if (fos != null) fos.close();
		}
	}

	public String toString()
	{
		if (mID != null)
			return(mID);
		if (mRoster!=null)
			return(mRoster.getDccAddress());
		return("No locomotive available");
	}

	public String ID()
	{ return(mID); }

	public void setContainer(JmriJFrame cnt) {
		mContainer = cnt;		
	}

	public MyConductor getConductor() {
		return null;
	}
}
